//
//  Copyright (C) 1998-2007 J. Andrew McLaughlin
//  Copyright (C) 2009 Vadim Ushakov
// 
//  This program is free software; you can redistribute it and/or modify it
//  under the terms of the GNU General Public License as published by the Free
//  Software Foundation; either version 2 of the License, or (at your option)
//  any later version.
// 
//  This program is distributed in the hope that it will be useful, but
//  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
//  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
//  for more details.
//  
//  You should have received a copy of the GNU General Public License along
//  with this program; if not, write to the Free Software Foundation, Inc.,
//  59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//

// This goes with the file kernelWindow.c

#if !defined(_KERNELWINDOWCOMPONENT_H)

#include "kernelMouse.h"
#include "kernelGraphic.h"
#include "kernelText.h"
#include "kernelVariableList.h"
#include <string.h>
#include <sys/window.h>

// Forward declarations, where necessary
struct _kernelWindow;

// The object that defines a GUI component inside a window
struct _kernelWindowComponent {
	kernelWindowObjectType type;
	kernelWindowObjectType subType;
	volatile struct _kernelWindow *window;
	volatile struct _kernelWindowComponent *container;
	volatile struct _kernelWindowComponent *contextMenu;
	kernelGraphicBuffer *buffer;
	int xCoord;
	int yCoord;
	int level;
	int width;
	int height;
	int minWidth;
	int minHeight;
	unsigned flags;
	componentParameters params;
	windowEventStream events;
	variableList* tags;

	void (*eventHandler)(volatile struct _kernelWindowComponent *, windowEvent *);
	int doneLayout;
	void *data;

	// Routines for managing this component.  These are set by the
	// kernelWindowComponentNew routine, for things that are common to all
	// components.
	int (*drawBorder) (volatile struct _kernelWindowComponent *, int);
	int (*erase) (volatile struct _kernelWindowComponent *);
	int (*grey) (volatile struct _kernelWindowComponent *);

	// Routines that should be implemented by components that 'contain'
	// or instantiate other components
	int (*add) (volatile struct _kernelWindowComponent *, volatile struct _kernelWindowComponent *);
	int (*remove) (volatile struct _kernelWindowComponent *, volatile struct _kernelWindowComponent *);
	int (*numComps) (volatile struct _kernelWindowComponent *);
	int (*flatten) (volatile struct _kernelWindowComponent *, volatile struct _kernelWindowComponent **, int *, unsigned);
	int (*layout) (volatile struct _kernelWindowComponent *);
	volatile struct _kernelWindowComponent * (*eventComp) (volatile struct _kernelWindowComponent *, int, int);
	int (*setBuffer) (volatile struct _kernelWindowComponent *, kernelGraphicBuffer *);

	// More routines for managing this component.  These are set by the
	// code which builds the instance of the particular component type
	int (*draw) (volatile struct _kernelWindowComponent *);
	int (*update) (volatile struct _kernelWindowComponent *);
	int (*move) (volatile struct _kernelWindowComponent *, int, int);
	int (*resize) (volatile struct _kernelWindowComponent *, int, int);
	int (*focus) (volatile struct _kernelWindowComponent *, int);
	int (*getData) (volatile struct _kernelWindowComponent *, void *, int);
	int (*setData) (volatile struct _kernelWindowComponent *, void *, int);
	int (*getDataEx) (volatile struct _kernelWindowComponent *, char *, void *, int);
	int (*setDataEx) (volatile struct _kernelWindowComponent *, char *, void *, int);
	int (*getSelected) (volatile struct _kernelWindowComponent *, int *);
	int (*setSelected) (volatile struct _kernelWindowComponent *, int);
	int (*mouseEvent) (volatile struct _kernelWindowComponent *, windowEvent *);
	int (*keyEvent) (volatile struct _kernelWindowComponent *, windowEvent *);
	int (*destroy) (volatile struct _kernelWindowComponent *);

};


static inline screenArea *makeComponentScreenArea(kernelWindowComponent *component)
{
	return (&((screenArea) {
		(component->window->xCoord + component->xCoord),
		(component->window->yCoord + component->yCoord),
		(component->window->xCoord + component->xCoord + (component->width - 1)),
		(component->window->yCoord + component->yCoord + (component->height - 1))
	}));
}

static inline void removeFromContainer(kernelWindowComponent *component)
{
	// Remove the component from its parent container
	if (component->container && component->container->remove)
		component->container->remove(component->container, component);
	component->container = NULL;
}

// Functions for managing components.  This first batch is from
// kernelWindowComponent.c
kernelWindowComponent *kernelWindowComponentNew(objectKey, componentParameters *);
void kernelWindowComponentDestroy(kernelWindowComponent *);
int kernelWindowComponentSetVisible(kernelWindowComponent *, int);
int kernelWindowComponentSetVisibleNoUpdate(kernelWindowComponent *, int);
int kernelWindowComponentSetEnabled(kernelWindowComponent *, int);
int kernelWindowComponentGetWidth(kernelWindowComponent *);
int kernelWindowComponentSetWidth(kernelWindowComponent *, int);
int kernelWindowComponentGetHeight(kernelWindowComponent *);
int kernelWindowComponentSetHeight(kernelWindowComponent *, int);
int kernelWindowComponentFocus(kernelWindowComponent *);
int kernelWindowComponentUnfocus(kernelWindowComponent *);
int kernelWindowComponentDraw(kernelWindowComponent *);
int kernelWindowComponentGetData(kernelWindowComponent *, void *, int);
int kernelWindowComponentSetData(kernelWindowComponent *, void *, int);
int kernelWindowComponentGetDataEx(kernelWindowComponent *, char *, void *, int);
int kernelWindowComponentSetDataEx(kernelWindowComponent *, char *, void *, int);
int kernelWindowComponentGetSelected(kernelWindowComponent *, int *);
int kernelWindowComponentSetSelected(kernelWindowComponent *, int);

// Constructors exported by the different component types
kernelWindowComponent *kernelWindowNewBorder(objectKey, borderType,
					     componentParameters *);
kernelWindowComponent *kernelWindowNewButton(objectKey, const char *,
					     image *, componentParameters *);
kernelWindowComponent *kernelWindowNewCanvas(objectKey, int, int,
					     componentParameters *);
kernelWindowComponent *kernelWindowNewCheckbox(objectKey, const char *,
					       componentParameters *);
kernelWindowComponent *kernelWindowNewContainer(objectKey, const char *,
						componentParameters *);
kernelWindowComponent *kernelWindowNewIcon(objectKey, image *,
					   const char *,
					   componentParameters *);
kernelWindowComponent *kernelWindowNewImage(objectKey, image *, drawMode,
					    componentParameters *);
kernelWindowComponent *kernelWindowNewList(objectKey, windowListType,
					   int, int, int, listItemParameters *,
					   int, componentParameters *);
kernelWindowComponent *kernelWindowNewListItem(objectKey, windowListType,
					       listItemParameters *,
					       componentParameters *);
kernelWindowComponent *kernelWindowNewMenu(objectKey, const char *,
					   windowMenuContents *,
					   componentParameters *);
kernelWindowComponent *kernelWindowNewMenuBar(kernelWindow *,
					      componentParameters *);
kernelWindowComponent *kernelWindowNewMenuItem(kernelWindowComponent *,
					       const char *,
					       componentParameters *);
kernelWindowComponent *kernelWindowNewPasswordField(objectKey, int,
						    componentParameters *);
kernelWindowComponent *kernelWindowNewProgressBar(objectKey,
						  componentParameters *);
kernelWindowComponent *kernelWindowNewRadioButton(objectKey, int, int,
						  const char **, int,
						  componentParameters *);
kernelWindowComponent *kernelWindowNewScrollBar(objectKey, scrollBarType,
						int, int,
						componentParameters *);
kernelWindowComponent *kernelWindowNewSlider(objectKey, scrollBarType,
					     int, int, componentParameters *);
kernelWindowComponent *kernelWindowNewSysContainer(kernelWindow *,
						   componentParameters *);
kernelWindowComponent *kernelWindowNewTextArea(objectKey, int, int, int,
					       componentParameters *);
kernelWindowComponent *kernelWindowNewTextField(objectKey, int,
						componentParameters *);
kernelWindowComponent *kernelWindowNewTextLabel(objectKey, const char *,
						componentParameters *);
kernelWindowComponent *kernelWindowNewTitleBar(kernelWindow *,
					       componentParameters *);


#define _KERNELWINDOWCOMPONENT_H
#endif
